/*
   Copyright (c) [Year] [name of copyright holder]
   [Software Name] is licensed under Mulan PSL v2.
   You can use this software according to the terms and conditions of the Mulan PSL v2. 
   You may obtain a copy of Mulan PSL v2 at:
            http://license.coscl.org.cn/MulanPSL2 
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
   See the Mulan PSL v2 for more details.  
*/

/*!
 * \autor captainpeng
 * \date 2019-12-15
 * \version 1.0
 * \copyright
 */

#ifndef JIAJIA_TABLE_HPP
#define JIAJIA_TABLE_HPP

namespace jiajia{
    // table 对象一棵存储 var 变量的树
    template<typename VALUETYPE>
    class table{
    public:
        using valueType = VALUETYPE;
        using varType = var<valueType>;
        using nameType = typename varType::nameType;
        using avlType = my::avl<varType>;

    private:
        avlType mTree;

    public:
        avlType & tree(){
            return mTree;
        }

        varType * insert(const nameType & key){
            return mTree.insertComp(varType::InitByName, varType::NameComp, key);
        }

        varType * find(const nameType & key){
            return mTree.findComp(varType::NameComp, key);
        }

        valueType * insertValue(const nameType & key){
            return &(this->insert(key)->value());
        }

        valueType * findValue(const nameType & key){
            varType * p = this->find(key);
            return (p == nullptr)? nullptr:&(p->value());
        }

        bool toString(std::string & s){
            bool flag = true;
            size_t size = mTree.size();
            s.append("{");
            mTree.each(
                [&size, &flag](varType & val, std::string & s)->bool{
                    flag = val.toString(s);
                    --size;
                    if(size != 0)
                        s.append(",");
                    return flag;
                }, s);
            s.append("}");
            return flag;
        }

        void free(){
            mTree.free();
        }
    };

    template<typename T>
    bool operator==(const table<T> & lhs, const table<T> & rhs){
        return lhs.tree() == rhs.tree();
    }

    template<typename T>
    bool operator!=(const table<T> & lhs, const table<T> & rhs){
        return !(lhs == rhs);
    }
}

#endif
